#pragma once

#include <iostream>
#include<string>
#include<unistd.h>
#include<atomic>
#include<fstream>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<boost/algorithm/string.hpp>

#include"Time.hpp"

namespace ns_Util
{

    const std::string file_path = "./temp/";
    class PathUtil
    {
        public:
            static std::string AddSuffix(const std::string &file_name, const std::string &suffix)
            {
                std::string path_name = file_path;
                path_name += file_name;
                path_name += suffix;
                return path_name;
            }

            //编译时生成的临时文件
            static std::string SRC(const std::string &file_name)
            {
                return AddSuffix(file_name, ".cpp");
            }
            static std::string EXE(const std::string &file_name)
            {
                return AddSuffix(file_name, ".exe");
            }
            static std::string COMPILERERR(const std::string &file_name)
            {
                return AddSuffix(file_name, ".compile_err");
            }

            //运行时生成的临时文件
            static std::string STDIN(const std::string &file_name)
            {
                return AddSuffix(file_name, ".stdin");
            }

            static std::string STDOUT(const std::string &file_name)
            {
                return AddSuffix(file_name, ".stdout");
            }

            static std::string STDERR(const std::string &file_name)
            {
                return AddSuffix(file_name, ".stderr");
            }
        private:
    };

    class FileUtil
    {
        public:
            static bool ISFILEEXIT(const std::string &file_name)
            {
                struct stat st;
                if(stat(file_name.c_str(), &st) == 0)
                {
                    return true;
                }
                return false;
            }   

            //文件名由毫秒级时间戳和自增长id组成
            static std::string UniqueFileName()
            {
                struct timeval tv;
                gettimeofday(&tv, nullptr);
                std::string time_str = std::to_string(tv.tv_sec * 1000 + tv.tv_usec / 1000);
                // std::string time_str = GetCurrTime();
                static std::atomic_uint id(0);
                id++;
                std::string id_str = std::to_string(id);
                return time_str  + "_" + id_str;
                
            }

            static bool WriteFile(const std::string &target, const std::string &content)
            {
                std::ofstream out(target);
                if(!out.is_open())
                {
                    return false;
                }
                out.write(content.c_str(), content.size());
                out.close();
                return true;
            }

            static bool ReadFile(const std::string &target,std::string *content,bool keep = false)
            {
                std::ifstream in(target);
                if(!in.is_open())
                {
                    return false;
                }

                std::string line;
                while(std::getline(in,line))
                {
                    *content += line;
                    *content += (keep ? "\n" : "");
                }
                in.close();
                return true;
            }

            static void SplitString(const std::string &target, std::vector<std::string> *tokens,const std::string &sep)
            {
                boost::split(*tokens, target, boost::is_any_of(sep),boost::token_compress_on);
            }
        private:
    };

    class TimeUtil
    {
        public:
            static std::string GetCurrentTime()
            {
                struct timeval tv;
                gettimeofday(&tv, NULL);
                return std::to_string(tv.tv_sec);
            }
        private:
    };
}